﻿using Admin.NET.Core;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MOKA.TPM.Application.Enum;
using MOKA.TPM.Application.Service.Dto;
using MOKA.TPM.Entity;
using MOKA.TPM.Service.Dto;
using MOKA.TPM.Utility.Const;
using SqlSugar;
using System.ComponentModel;

namespace MOKA.TPM.Service;

/// <summary>
/// 数据字典明细服务
/// </summary>
[ApiDescriptionSettings(TPMConst.GroupName, Order = 860)]
public class Service_SysDictDetail : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<SysDictCode> _repSysDictCode;
    private readonly SqlSugarRepository<SysDictDetail> _rep;
    private readonly UserManager _userManager;
    private IHttpContextAccessor _accessor;//获取请求上下文_userRepository
    private readonly ISqlSugarClient _db;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="db"></param>
    /// <param name="rep"></param>
    /// <param name="userManager"></param>
    /// <param name="accessor"></param>
    public Service_SysDictDetail(ISqlSugarClient db, SqlSugarRepository<SysDictDetail> rep, UserManager userManager, IHttpContextAccessor accessor, SqlSugarRepository<SysDictCode> repSysDictCode)
    {
        _db = db;
        _rep = rep;
        _userManager = userManager;
        _accessor = accessor;
        _repSysDictCode = repSysDictCode;
    }

    /// <summary>
    /// 获取分页列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("获取分页列表")]
    public async Task<SqlSugarPagedList<SysDictDetailOutput>> Page(PageSysDictDetailInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictDetail>()
            .IncludesAllSecondLayer(a => a.sysDictCode_DictCodeID)
            .Includes(a => a.sysDictDetail_ItemParent)
            .IncludesAllSecondLayer(a => a.t__USER_CreateUser)
            .IncludesAllSecondLayer(a => a.t__USER_UpdateUser)
            .WhereIF(!string.IsNullOrEmpty(input.ItemName?.Trim()), u => u.ItemName.Contains(input.ItemName))
            .Where(a => a.IsDelete == false)
            .Select((a) => new SysDictDetailOutput()
            {
                Id = a.Id.SelectAll(),
                CatCode = a.sysDictCode_DictCodeID.CatCode,
                CatName = a.sysDictCode_DictCodeID.CatName,
                ItemParentName = a.sysDictDetail_ItemParent.ItemName,//字典
                sysDictCode_DictCodeID = a.sysDictCode_DictCodeID,
                sysDictDetail_ItemParent = a.sysDictDetail_ItemParent,
                t__USER_CreateUser = a.t__USER_CreateUser,
                t__USER_UpdateUser = a.t__USER_UpdateUser,
            })
            .Mapper((item) =>
            {
                //Mapster映射转换，不能有SQL
                //TypeAdapterConfig config = new TypeAdapterConfig()
                //.ForType<ContractFile, ContractFileOutput>()
                //.IgnoreIf((src, dest) => src.File == null, "Id", "Name", "FileType", "FileName", "Suffix", "FilePath", "SizeKb", "Url")
                //    .Map(dest => dest.Id, src => src.File.Id)
                //    .Map(dest => dest.Name, src => src.File.Id + src.File.Suffix)
                //.Config
                //.ForType<JToken, JToken>()
                //    .MapWith(json => json)
                //.Config;
                //item.ContractBody = item.ContractBodyIn.Adapt<List<ContractFileOutput>>(config);
            })
            .OrderBuilder(input) //(input, "a.", "PartNo", false)
            .ToPagedListAsync(input.Page, input.PageSize);

        return lists;
    }

    /// <summary>
    /// 获取列表 🔖
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取列表")]
    [AllowAnonymous]
    public async Task<List<SysDictDetailOutput>> GetList([FromQuery] GetSysDictDetailInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictDetail>()
            .IncludesAllSecondLayer(a => a.sysDictCode_DictCodeID)
            .Includes(a => a.sysDictDetail_ItemParent)

            .IncludesAllSecondLayer(a => a.t__USER_CreateUser)
            .IncludesAllSecondLayer(a => a.t__USER_UpdateUser)
            .WhereIF(input.DictCodeID.HasValue, a => a.DictCodeID == input.DictCodeID)
            .WhereIF(input.Status.HasValue, a => a.Status == input.Status)
            .Where(a => a.IsDelete == false)
            .OrderByDescending(a => a.Id)
            .Select((a) => new SysDictDetailOutput()
            {
                Id = a.Id.SelectAll(),
                CatCode = a.sysDictCode_DictCodeID.CatCode,
                CatName = a.sysDictCode_DictCodeID.CatName,
                ItemParentName = a.sysDictDetail_ItemParent.ItemName,//字典
                sysDictCode_DictCodeID = a.sysDictCode_DictCodeID,
                sysDictDetail_ItemParent = a.sysDictDetail_ItemParent,
                t__USER_CreateUser = a.t__USER_CreateUser,
                t__USER_UpdateUser = a.t__USER_UpdateUser,
            })
            .Mapper((item) =>
            {
                //Mapster映射转换，不能有SQL
                //TypeAdapterConfig config = new TypeAdapterConfig()
                //.ForType<ContractFile, ContractFileOutput>()
                //.IgnoreIf((src, dest) => src.File == null, "Id", "Name", "FileType", "FileName", "Suffix", "FilePath", "SizeKb", "Url")
                //    .Map(dest => dest.Id, src => src.File.Id)
                //    .Map(dest => dest.Name, src => src.File.Id + src.File.Suffix)
                //.Config
                //.ForType<JToken, JToken>()
                //    .MapWith(json => json)
                //.Config;
                //item.ContractBody = item.ContractBodyIn.Adapt<List<ContractFileOutput>>(config);
            })
            .Take(20)//为了性能，只取20个。
            .ToListAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取单个对象 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取单个对象")]
    [AllowAnonymous]
    public async Task<SysDictDetailOutput> GetOne([FromQuery] SysDictDetailInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictDetail>()
            .IncludesAllSecondLayer(a => a.sysDictCode_DictCodeID)
            .Includes(a => a.sysDictDetail_ItemParent)
            .IncludesAllSecondLayer(a => a.t__USER_CreateUser)
            .IncludesAllSecondLayer(a => a.t__USER_UpdateUser)
            .WhereIF(!string.IsNullOrEmpty(input.ItemValue), a => a.ItemValue == input.ItemValue
                    && a.ItemParent == input.ItemParent
                    && a.DictCodeID == input.DictCodeID)//唯一索引
            .WhereIF(input.Id.HasValue, a => a.Id == input.Id)
            .OrderBy((a) => new { a.sysDictCode_DictCodeID.CatCode, a.FNOrder, a.ItemValue })
            .Select((a) => new SysDictDetailOutput()
            {
                Id = a.Id.SelectAll(),
                ItemParentName = a.sysDictDetail_ItemParent.ItemName,//字典
                sysDictCode_DictCodeID = a.sysDictCode_DictCodeID,
                sysDictDetail_ItemParent = a.sysDictDetail_ItemParent,
                t__USER_CreateUser = a.t__USER_CreateUser,
                t__USER_UpdateUser = a.t__USER_UpdateUser,
            })
            .SingleAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 添加 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    [DisplayName("添加")]
    [AllowAnonymous]
    public async Task<bool> AddData(AddSysDictDetailInput input)
    {
        var isExist = await _rep.IsAnyAsync(u => u.DictCodeID == input.DictCodeID && u.ItemParent == input.ItemParent && u.ItemValue == input.ItemValue); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典目录", input.DictCodeID + "父项", input.ItemParent + "项目值（代码）", input.ItemValue);
        }

        var entity = input.Adapt<SysDictDetail>(); //将AddSysDictDetailInput转成SysDictDetail

        //entity.Code = "thisCode"; //后台生成字段值

        //启动事务
        using (var uow = _db.CreateContext())
        {
            var ret = await _rep.AsInsertable(entity).EnableDiffLogEvent().ExecuteReturnEntityAsync();//插入后返回实体

            //提交事务
            uow.Commit();
            return ret != null;
        }
    }

    /// <summary>
    /// 更新 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    [DisplayName("更新")]
    [AllowAnonymous]
    public async Task<bool> UpdateData(UpdateSysDictDetailInput input)
    {
        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        isExist = await _rep.IsAnyAsync(u => u.DictCodeID == input.DictCodeID && u.ItemParent == input.ItemParent && u.ItemValue == input.ItemValue && u.Id != input.Id); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典目录", input.DictCodeID + "父项", input.ItemParent + "项目值（代码）", input.ItemValue);
        }
        var entity = input.Adapt<SysDictDetail>(); //将UpdateSysDictDetailInput转成SysDictDetail

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).IgnoreNullColumns().EnableDiffLogEvent().ExecuteCommandAsync() > 0;

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 删除 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    [DisplayName("删除")]
    [AllowAnonymous]
    public async Task<bool> DeleteData(DeleteSysDictDetailInput input)
    {
        var entity = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.Context.Deleteable(entity).EnableDiffLogEvent().ExecuteCommandAsync() > 0;
            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 修改部分数据 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateSome"), HttpPost]
    [DisplayName("修改部分数据")]
    [AllowAnonymous]
    public async Task<bool> UpdateSomeData(UpdateSomeSysDictDetailInput input)
    {
        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);
        }

        var entity = input.Adapt<SysDictDetail>(); //将UpdateSysDictDetailInput转成SysDictDetail
        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).UpdateColumns(it => new { it.Status, }).ExecuteCommandAsync() > 0;

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 批量添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "AddRange"), HttpPost]
    [DisplayName("批量添加")]
    [AllowAnonymous]
    public async Task<int> AddBulkData(List<SysDictDetail> input)
    {
        foreach (var item in input)
        {
            var isExist = await _rep.IsAnyAsync(u => u.DictCodeID == item.DictCodeID && u.ItemParent == item.ItemParent && u.ItemValue == item.ItemValue); //唯一索引是否存在
            if (isExist)
            {
                throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典目录", item.DictCodeID + "父项", item.ItemParent + "项目值（代码）", item.ItemValue);
            }
        }

        //启动事务
        using (var uow = _db.CreateContext())
        {
            int ret = await _rep.Context.Insertable(input).ExecuteCommandAsync();
            //不需要上传详细表了

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 获取所有TPMDeviceGroup
    /// </summary>
    [AllowAnonymous]
    [DisplayName("获取所有TPMDeviceGroup")]
    public async Task<List<SysDictDetail>> GetTPMGroups()
    {
        return await GetDetailListByDictCode("TPMDeviceGroup", TPMDeviceGroupEnum.CommonGroup);
    }

    /// <summary>
    /// 根据字典目录编码获取字典值集合 🔖
    /// </summary>
    /// <param name="DictCode"></param>
    /// <param name="TPMDeviceGroupCode"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("根据字典类型编码获取字典值集合")]
    public async Task<List<SysDictDetail>> GetDetailListByDictCode([FromQuery] string DictCode, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await _rep.Context.Queryable<SysDictCode>()
                .LeftJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
                .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
                .Where((a, b, c) => a.CatCode == DictCode
                            && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString()))
                .OrderBy((a, b, c) => new { b.FNOrder })
                .Select((a, b, c) => b).ToListAsync();

        return dictDataList;
    }

    /// <summary>
    /// 获取字典类型-值列表 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [AllowAnonymous]
    [DisplayName("获取字典类型-值列表")]
    public async Task<List<SysDictDetailOutput>> GetDetailList([FromQuery] SysDictCodeInput input)
    {
        var dictType = await _repSysDictCode.GetFirstAsync(u => u.CatCode == input.CatCode) ?? throw Oops.Oh(ErrorCodeEnum.D3000);

        var lists = await _rep.AsQueryable()
           .LeftJoin<SysDictCode>((a, b) => a.DictCodeID == b.Id) //主表
           .LeftJoin<SysDictDetail>((a, b, c) => a.ItemParent == c.Id) //父表
           .WhereIF(!string.IsNullOrEmpty(input.CatCode), (a, b) => b.CatCode == input.CatCode)
           .OrderBy((a, b) => new { b.CatCode, a.FNOrder, a.ItemValue })
           .Select((a, b, c) => new SysDictDetailOutput()
           {
               Id = a.Id.SelectAll(),
               CatCode = b.CatCode,
               CatName = b.CatName,
               ItemParentName = c.ItemName,
               // ItemParentObject = c,
           })
           .ToListAsync();
        return lists;
    }

    /// <summary>
    /// 根据值获取TPMGroup
    /// </summary>
    [AllowAnonymous]
    [DisplayName("根据值获取TPMGroup")]
    public async Task<SysDictDetailOutput> GetTPMGroupByItemValue([FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await GetDetailByItemValue("TPMDeviceGroup", TPMDeviceGroupCode.ToString(), TPMDeviceGroupEnum.CommonGroup);
        return dictDataList;
    }

    /// <summary>
    /// 根据值获取单一
    /// </summary>
    [AllowAnonymous]
    [DisplayName("根据值获取单一")]
    public async Task<SysDictDetailOutput> GetDetailByItemValue([FromQuery] string DictCode, [FromQuery] string ItemValue, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await _rep.Context.Queryable<SysDictCode>()
                .LeftJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
                .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
                .Where((a, b, c) => a.CatCode == DictCode
                         && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString())
                         && b.ItemValue == ItemValue)
                .OrderBy((a, b, c) => new { b.FNOrder })
                .Select((a, b, c) => new SysDictDetailOutput()
                {
                    Id = b.Id.SelectAll(),
                    CatCode = a.CatCode,
                    CatName = a.CatName,
                    //ItemParenName = c.ItemName,
                }).SingleAsync();
        return dictDataList;
    }

    /// <summary>
    /// 根据名称获取单一
    /// </summary>
    [AllowAnonymous]
    [DisplayName("根据名称获取单一")]
    public async Task<SysDictDetailOutput> GetDetailByItemName([FromQuery] string DictCode, [FromQuery] string ItemName, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await _rep.Context.Queryable<SysDictCode>()
                .LeftJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
                .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
                .Where((a, b, c) => a.CatCode == DictCode
                         && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString())
                         && b.ItemName == ItemName)
                .OrderBy((a, b, c) => new { b.FNOrder })
                .Select((a, b, c) => new SysDictDetailOutput()
                {
                    Id = b.Id.SelectAll(),
                    CatCode = a.CatCode,
                    CatName = a.CatName,
                    //ItemParenName = c.ItemName,
                })
                .SingleAsync();
        return dictDataList;
    }

    /// <summary> 根据名称2获取单一,比如根据成本中心获取车间
    [AllowAnonymous] /// </summary>
    [DisplayName("根据名称3获取单一,比如根据成本中心获取车间")]
    public async Task<SysDictDetailOutput> GetDetailByItemName2([FromQuery] string DictCode, [FromQuery] string ItemName2, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await _rep.Context.Queryable<SysDictCode>()
                .LeftJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
                .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
                .Where((a, b, c) => a.CatCode == DictCode
                         && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString())
                         && b.ItemName2 == ItemName2)
                .OrderBy((a, b, c) => new { b.FNOrder })
                .Select((a, b, c) => new SysDictDetailOutput()
                {
                    Id = b.Id.SelectAll(),
                    CatCode = a.CatCode,
                    CatName = a.CatName,
                    //ItemParenName = c.ItemName,
                })
                .SingleAsync();
        return dictDataList;
    }

    /// <summary>
    /// 根据名称3获取单一，比如根据用户名获取车间
    /// </summary>
    [AllowAnonymous]
    [DisplayName("根据名称3获取单一,比如根据用户名获取车间")]
    public async Task<SysDictDetailOutput> GetDetailByItemName3([FromQuery] string DictCode, [FromQuery] string ItemName3, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictDataList = await _rep.Context.Queryable<SysDictCode>()
                .LeftJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
                .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
                .Where((a, b, c) => a.CatCode == DictCode
                         && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString())
                         && b.ItemName3 == ItemName3)
                .OrderBy((a, b, c) => new { b.FNOrder })
                .Select((a, b, c) => new SysDictDetailOutput()
                {
                    Id = b.Id.SelectAll(),
                    CatCode = a.CatCode,
                    CatName = a.CatName,
                    //ItemParenName = c.ItemName,
                })
                .SingleAsync();
        return dictDataList;
    }

    /// <summary>
    /// 获取多个目录的的详细数据
    /// </summary>
    /// <param name="DictCodes"></param>
    /// <param name="TPMDeviceGroupCode"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("获取多个目录的的详细数据")]
    public async Task<List<SysDictDetailOutput>> GetDetailListByDictCodes([FromQuery] string DictCodes, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var dictCodeList = DictCodes.Split(",").ToList();
        var dictDataList = await _rep.AsQueryable()
        .Includes((a) => a.sysDictDetail_ItemParent)
        .Includes((a) => a.sysDictCode_DictCodeID)
        //.LeftJoin<SysDictCode>((a, b) => b.Id == a.DictCodeID)
        .LeftJoin<SysDictDetail>((a, b) => a.sysDictCode_DictCodeID.TPMDeviceGroupId == b.Id)

        .Where((a, b) => dictCodeList.Contains(a.sysDictCode_DictCodeID.CatCode)
                && (b.ItemValue == TPMDeviceGroupCode.ToString() || b.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString()))
        .OrderBy((a, b) => new { a.FNOrder })
        .Select((a, b) => new SysDictDetailOutput()
        {
            Id = a.Id.SelectAll(),
            CatCode = a.sysDictCode_DictCodeID.CatCode,
            CatName = a.sysDictCode_DictCodeID.CatName,
            sysDictDetail_ItemParent = a.sysDictDetail_ItemParent,
            sysDictCode_DictCodeID = a.sysDictCode_DictCodeID,
        })
        .ToListAsync();

        return dictDataList;
    }

    /// <summary>
    /// 根据ItemParent获取列表
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("根据ItemParent获取列表")]
    public async Task<List<SysDictDetailOutput>> GetDetailListByItemParent([FromQuery] string DictCode, [FromQuery] Guid ItemParent, [FromQuery] TPMDeviceGroupEnum TPMDeviceGroupCode)
    {
        var lists = await _rep.Context.Queryable<SysDictCode>()
            .InnerJoin<SysDictDetail>((a, b) => a.Id == b.DictCodeID)
            .LeftJoin<SysDictDetail>((a, b, c) => a.TPMDeviceGroupId == c.Id)
            .InnerJoin<SysDictDetail>((a, b, c, d) => b.ItemParent == d.Id) //父表
            .Where((a, b, c, d) => a.CatCode == DictCode
                         && (c.ItemValue == TPMDeviceGroupCode.ToString() || c.ItemValue == TPMDeviceGroupEnum.CommonGroup.ToString())
                         && b.ItemParent == ItemParent)
            .OrderBy((a, b) => new { a.CatCode, b.FNOrder, b.ItemValue })
            .Select((a, b, c, d) => new SysDictDetailOutput()
            {
                Id = b.Id.SelectAll(),
                CatCode = a.CatCode,
                CatName = a.CatName,
                ItemParentName = d.ItemName,
            })
            .ToListAsync();

        return lists;
    }
}